package com.sita.redsun.connector.handler;

import com.sita.redsun.connector.mqtthandler.Utils;
import com.test.protocol.messages.*;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.handler.codec.mqtt.*;
import io.netty.util.ReferenceCountUtil;
import org.apache.activemq.broker.region.Subscription;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


import java.io.UnsupportedEncodingException;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.List;

import static com.test.protocol.messages.AbstractMessage.*;
import static io.netty.channel.ChannelFutureListener.CLOSE_ON_FAILURE;
import static io.netty.handler.codec.mqtt.MqttQoS.AT_MOST_ONCE;

/**
 * Created by zhebinwang on 2018/5/26.
 */
public class MqttHandler  extends ChannelInboundHandlerAdapter {
    private static final Logger LOG = LoggerFactory.getLogger(MqttHandler.class);
   // private final ProtocolProcessor m_processor;

  /*  public MqttHandler(ProtocolProcessor processor) {
        m_processor = processor;
    }*/

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object message) {
        com.test.protocol.messages.ConnectMessage mm;
        AbstractMessage pmsg=(AbstractMessage) message;
        LOG.debug("read"+message.toString());
        //java.lang.ClassCastException: com.test.protocol.messages.ConnectMessage cannot be cast to io.netty.handler.codec.mqtt.MqttMessage;
        System.out.println("收到一个消息 类型是  "+pmsg.getMessageType());

        //LOG.debug();
        switch(pmsg.getMessageType()){
            case CONNECT:
                ConnectMessage ipmsg=(ConnectMessage) message;
                byte[] b=ipmsg.getWillMessage();
                byte[] password=ipmsg.getPassword();
                ConnAckMessage camsg=new ConnAckMessage();
                camsg.setReturnCode(ConnAckMessage.CONNECTION_ACCEPTED);
                //camsg.setQos(0);
                ctx.writeAndFlush(camsg);



                System.out.println("show");
                break;
            //case PUBLISH:
            case PUBLISH:
                PublishMessage publishmsg=(PublishMessage) message;

                ByteBuffer bb= publishmsg.getPayload();
                byte[] bytes = new byte[bb.remaining()];
                bb.get(bytes,0,bb.remaining());
                String srt2="";
                try {
                     srt2=new String(bytes,"GBK");
                } catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
                }
                System.out.println("show publish "+ srt2);
                PubAckMessage pubAckMessage = new PubAckMessage();
                pubAckMessage.setMessageID(publishmsg.getMessageID());
                //session.write(pubAckMessage);
                //camsg.setQos(0);
                ctx.writeAndFlush(pubAckMessage);
                break;
            case SUBSCRIBE:
                SubscribeMessage ssbmsg=(SubscribeMessage)message;
                SubAckMessage ackMessage = new SubAckMessage();
                ackMessage.setMessageID(ssbmsg.getMessageID());

                for (SubscribeMessage.Couple req : ssbmsg.subscriptions()) {
                    System.out.println("客户端订阅了"+ req.getTopicFilter());
                    AbstractMessage.QOSType qos = AbstractMessage.QOSType.valueOf(req.getQos());
                    ackMessage.addType(qos);
                   /* AbstractMessage.QOSType qos = AbstractMessage.QOSType.valueOf(req.getQos());
                    Subscription newSubscription = new Subscription("aa", req.getTopicFilter(), qos);
                    //boolean valid = subscribeSingleTopic(newSubscription, req.getTopicFilter());
                    boolean valid = clientSession.subscribe(req.getTopicFilter(), newSubscription);
                    ackMessage.addType(valid ? qos : AbstractMessage.QOSType.FAILURE);
                    if (valid) {
                        newSubscriptions.add(newSubscription);
                    }*/
                }

                ctx.writeAndFlush(ackMessage);
                break;
            case PINGREQ:  //心跳请求 直接回应
                PingReqMessage prmsg=(PingReqMessage)message;
                //PingRespMessage pingResp = new PingRespMessage();
                ctx.writeAndFlush(prmsg);

        }

        try {
           /* switch (messageType) {
                case CONNECT:
                    m_processor.processConnect(ctx.channel(), (MqttConnectMessage) msg);
                    break;
                case SUBSCRIBE:
                    m_processor.processSubscribe(ctx.channel(), (MqttSubscribeMessage) msg);
                    break;
                case UNSUBSCRIBE:
                    m_processor.processUnsubscribe(ctx.channel(), (MqttUnsubscribeMessage) msg);
                    break;
                case PUBLISH:
                    m_processor.processPublish(ctx.channel(), (MqttPublishMessage) msg);
                    break;
                case PUBREC:
                    m_processor.processPubRec(ctx.channel(), msg);
                    break;
                case PUBCOMP:
                    m_processor.processPubComp(ctx.channel(), msg);
                    break;
                case PUBREL:
                    m_processor.processPubRel(ctx.channel(), msg);
                    break;
                case DISCONNECT:
                    m_processor.processDisconnect(ctx.channel());
                    break;
                case PUBACK:
                    m_processor.processPubAck(ctx.channel(), (MqttPubAckMessage) msg);
                    break;
                case PINGREQ:
                    MqttFixedHeader pingHeader = new MqttFixedHeader(
                            MqttMessageType.PINGRESP,
                            false,
                            AT_MOST_ONCE,
                            false,
                            0);
                    MqttMessage pingResp = new MqttMessage(pingHeader);
                    ctx.writeAndFlush(pingResp).addListener(CLOSE_ON_FAILURE);
                    break;
                default:
                    LOG.error("Unknown MessageType: {}", messageType);
                    break;
            }*/
        } catch (Throwable ex) {
            ctx.fireExceptionCaught(ex);
        } finally {
            ReferenceCountUtil.release(message);
        }
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) {
       /* String clientID = NettyUtils.clientID(ctx.channel());
        if (clientID != null && !clientID.isEmpty()) {
            LOG.info("Notifying connection lost event. MqttClientId = {}", clientID);
            m_processor.processConnectionLost(clientID, ctx.channel());
        }*/
        ctx.close().addListener(CLOSE_ON_FAILURE);
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
       /* LOG.error("Unexpected exception while processing MQTT message. Closing Netty channel. CId={}",
                NettyUtils.clientID(ctx.channel()), cause);*/
        ctx.close().addListener(CLOSE_ON_FAILURE);
    }

    @Override
    public void channelWritabilityChanged(ChannelHandlerContext ctx) {
       /* if (ctx.channel().isWritable()) {
            m_processor.notifyChannelWritable(ctx.channel());
        }*/
        ctx.fireChannelWritabilityChanged();
    }





}
